home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Dr. Windows 3
/
dr win3.zip
/
dr win3
/
PROGRAMR
/
OLE2BOOK.ZIP
/
CHAP05.ZIP
/
CHAP05
/
SMASHER
/
SMASHER.CPP
< prev
next >
Wrap
C/C++ Source or Header
|
1993-03-28
|
9KB
|
342 lines
/*
* SMASHER.CPP
*
* Functions to demonstrate a File Manager extension DLL that implements
* a toolbar button to defragment selected compound files.
*
* Copyright (c)1993 Microsoft Corporation, All Rights Reserved.
*
* Kraig Brockschmidt, Software Design Engineer
* Microsoft Systems Developer Relations
*
* Internet : kraigb@microsoft.com
* Compuserve: >INTERNET:kraigb@microsoft.com
*
*/
#include <windows.h>
#include <ole2.h>
#include "wfext.h" //Windows for Workgroups version.
#include "smasher.h"
HINSTANCE g_hInst;
BOOL fInitialized;
//Toolbar to place on Windows for Workgroups File Manager.
EXT_BUTTON btns[1]={{IDM_SMASH, IDS_SMASHHELP+1, 0}};
/*
* LibMain
*
* Purpose:
* DLL-specific entry point called from LibEntry. Initializes
* global variables and loads standard image bitmaps.
*
* Parameters:
* hInstance HINSTANCE instance of the DLL.
* wDataSeg WORD segment selector of the DLL's data segment.
* wHeapSize WORD byte count of the heap.
* lpCmdLine LPSTR to command line used to start the module.
*
* Return Value:
* HANDLE Instance handle of the DLL.
*/
HANDLE FAR PASCAL LibMain(HINSTANCE hInstance, WORD wDataSeg
, WORD cbHeapSize, LPSTR lpCmdLine)
{
//Remember our instance.
g_hInst=hInstance;
if (0!=cbHeapSize)
UnlockData(0);
return hInstance;
}
/*
* WEP
*
* Purpose:
* Required DLL Exit function. Does nothing.
*
* Parameters:
* bSystemExit BOOL indicating if the system is being shut
* down or the DLL has just been unloaded.
*
* Return Value:
* void
*
*/
void FAR PASCAL WEP(int bSystemExit)
{
return;
}
/*
* FMExtensionProc
*
* Purpose:
* File Manager Extension callback function, receives messages from
* file manager when extension toolbar buttons and commands are
* invoked.
*
* Parameters:
* hWnd HWND of File Manager.
* iMsg UINT message identifier
* lParam LONG extra information.
*
* Return Value:
* HMENU
*/
HMENU FAR PASCAL FMExtensionProc(HWND hWnd, UINT iMsg, LONG lParam)
{
HMENU hMenu=NULL;
HRESULT hr;
LPMALLOC pIMalloc;
LPFMS_LOAD pLoad;
LPFMS_TOOLBARLOAD pTool;
LPFMS_HELPSTRING pHelp;
switch (iMsg)
{
case FMEVENT_LOAD:
pLoad=(LPFMS_LOAD)lParam;
pLoad->dwSize=sizeof(FMS_LOAD);
/*
* Check if our host did CoInitialize by trying CoGetMalloc.
* If it doesn't work, then we'll CoInitialize ourselves.
*/
hr=CoGetMalloc(MEMCTX_TASK, &pIMalloc);
if (SUCCEEDED(hr))
pIMalloc->Release();
else
{
hr=CoInitialize(NULL);
if (FAILED(hr))
return NULL;
fInitialized=TRUE;
}
//Assign the popup menu name for extension
LoadString(g_hInst, IDS_SMASH, pLoad->szMenuName
, sizeof(pLoad->szMenuName));
//Load the popup menu
pLoad->hMenu=LoadMenu(g_hInst, MAKEINTRESOURCE(IDR_MENU));
return pLoad->hMenu;
case FMEVENT_UNLOAD:
if (fInitialized)
CoUninitialize();
break;
case FMEVENT_TOOLBARLOAD:
/*
* File Manager has loaded our toolbar extension, so fill
* the TOOLBARLOAD structure with information about our
* buttons. This is only for Windows for Workgroups.
*/
pTool=(LPFMS_TOOLBARLOAD)lParam;
pTool->lpButtons= (LPEXT_BUTTON)&btns;
pTool->cButtons = 1;
pTool->cBitmaps = 1;
pTool->idBitmap = IDR_BITMAP;
break;
case FMEVENT_HELPSTRING:
//File Manager is requesting a status-line help string.
pHelp=(LPFMS_HELPSTRING)lParam;
LoadString(g_hInst, IDS_SMASHHELP+pHelp->idCommand
, pHelp->szHelp, sizeof(pHelp->szHelp));
break;
case IDM_SMASH:
SmashSelectedFiles(hWnd);
break;
}
return hMenu;
}
/*
* SmashSelectedFiles
*
* Purpose:
* Retrieves the list of selected files from File Manager and
* attempts to compress each one.
*
* Parameters:
* hWnd HWND of the File Manager message processing window
* that we send messages to in order to retrieve the
* count of selected files and their filenames.
*
* Return Value:
* BOOL TRUE if the function was successful, FALSE otherwise.
*/
BOOL SmashSelectedFiles(HWND hWnd)
{
FMS_GETFILESEL fms;
UINT cFiles;
UINT i;
LPSTR pszErr;
HRESULT hr;
STATSTG st;
OFSTRUCT of;
LPMALLOC pIMalloc;
LPSTORAGE pIStorageOld;
LPSTORAGE pIStorageNew;
/*
* Retrieve information from File Manager about the selected
* files and allocate memory for the paths and filenames.
*/
//Get the number of selected items.
cFiles=(UINT)SendMessage(hWnd, FM_GETSELCOUNT, 0, 0L);
//Nothing to do, so quit.
if (0==cFiles)
return TRUE;
//Get error string memory
hr=CoGetMalloc(MEMCTX_TASK, &pIMalloc);
if (FAILED(hr))
return FALSE;
pszErr=(LPSTR)pIMalloc->Alloc(1024);
/*
* Enumerate the selected files and directories using the FM_GETFILESEL
* message to the File Manager window. For each file, check if its
* a Compound File (StgIsStorageFile) and if not, skip it.
*
* If it is a compound file, then create a temp file and ::CopyTo
* from old to new. If this works, then we reopen the old file
* in overwrite mode and ::CopyTo back into it.
*/
for (i = 0; i < cFiles; i++)
{
SendMessage(hWnd, FM_GETFILESEL, i, (LONG)(LPSTR)&fms);
//Skip non-storages.
hr=StgIsStorageFile(fms.szName);
if (FAILED(hr))
{
wsprintf(pszErr, SZERRNOTACOMPOUNDFILE, (LPSTR)fms.szName);
MessageBox(hWnd, pszErr, SZSMASHER, MB_OK | MB_ICONHAND);
continue;
}
/*
* Create a temporary Compound File. We don't use DELETEONRELEASE
* in case we have to save it when coying over the old file fails.
*/
hr=StgCreateDocfile(NULL, STGM_CREATE | STGM_DIRECT | STGM_READWRITE
| STGM_SHARE_EXCLUSIVE, 0, &pIStorageNew);
if (FAILED(hr))
{
MessageBox(hWnd, SZERRTEMPFILE, SZSMASHER, MB_OK | MB_ICONHAND);
continue;
}
//Open the existing file as read-only
hr=StgOpenStorage(fms.szName, NULL, STGM_DIRECT | STGM_READ
| STGM_SHARE_DENY_WRITE, NULL, 0, &pIStorageOld);
if (FAILED(hr))
{
pIStorageNew->Release();
wsprintf(pszErr, SZERROPENFAILED, (LPSTR)fms.szName);
MessageBox(hWnd, pszErr, SZSMASHER, MB_OK | MB_ICONHAND);
continue;
}
/*
* Compress with ::CopyTo. Since the temp is opened in
* direct mode, changes are immediate.
*/
hr=pIStorageOld->CopyTo(NULL, NULL, NULL, pIStorageNew);
pIStorageOld->Release();
if (FAILED(hr))
{
pIStorageNew->Release();
MessageBox(hWnd, SZERRTEMPFILECOPY, SZSMASHER, MB_OK | MB_ICONHAND);
continue;
}
//Temp file contains the defragmented copy now, try copying back.
hr=StgOpenStorage(fms.szName, NULL, STGM_DIRECT | STGM_CREATE
| STGM_WRITE | ST